<?php
if ( ! defined( 'MEDIAWIKI' ) )
	die();

/**
 * Twitter and Identi.ca feed integration for MediaWiki
 * @addtogroup Extensions
 *
 * @link http://www.mediawiki.org/wiki/Extension:Tweeter Documentation
 * @author Aude
 * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
 * 
 * TODO:
 *  - more i18n internationalization
 *  - support search feeds
 *  - support template tags
 *  - validate params
 *     - check that username exists and security checks
 *  - parser tests
 *  - deal with Twitter API limits
 *  - instead of Curl, use built-in MediaWiki functions? pros/cons
 *  - use xml or other type of feed, rather than json?
 *  - use atom or rss feed instead of json?
 *  - or use javascript / jquery to fetch twitter feeds
*/

$dir = dirname(__FILE__);
$wgExtensionFunctions[] = 'wfTweeter';
$wgExtensionCredits['parserhook'][] = array(
        'name' => 'Tweeter',
        'description' => 'Twitter feed integration for MediaWiki',
        'author' => 'Aude',
        'url' => 'http://firststrike.net'
);

$wgExtensionMessagesFiles['Tweeter'] = "$dir/Tweeter.i18n.php";

$wgAutoloadClasses['Tweet'] = "$dir/classes/Tweet.php";
$wgAutoloadClasses['Service'] = "$dir/classes/Service.php";
$wgAutoloadClasses['Curl'] = "$dir/classes/Curl.php";
$wgAutoloadClasses['TweeterHooks'] = "$dir/classes/TweeterHooks.php";

$wgHooks['BeforePageDisplay'][] = 'TweeterHooks::addResources';

/**
 * configuration 
 */
$egServices = array( 
	'twitter' => array( 'servicename' => 'twitter',
				'serviceurl' => 'http://twitter.com/',
				'searchurl' => 'http://search.twitter.com/' ),
	'identica' => array( 'servicename' => 'identi.ca',
				'serviceurl' => 'http://identi.ca/api/',
				'searchurl' => 'http://identi.ca/api/' )
);

$egDefaultService = 'twitter';
$egDefaultCount = 5;
$egMaxTweets = 10;

/** 
 * parser functions
 */
function wfTweeter() {
	global $wgParser;
	$wgParser->setHook( 'twitter', 'renderTweets' );
}

function renderTweets( $input, $args ) {
	global $egDefaultCount, $egDefaultService, $egMaxTweets, $egServices;

	$user = null;
	$count = null;
	$service = null;

	foreach( $args as $k => $v ) {
		switch ( $k ) {
			case 'user':
				// TODO - validate input
				$user = $v;
				break;
			case 'count':
				if ( $v != strval( intval( $v ) ) ) {
					return tweetError( 'Not a valid count value' );
				} elseif ( $v > $egMaxTweets ) {
					return tweetError( 'Tweet count more than max allowed' );
				} else {
					$count = intval( $v );
				}					
				break;
			case 'service':
				if ( ! array_key_exists( $v, $egServices ) ) {
					return tweetError( 'Invalid service' );
				} else {
					$service = $v;
				}
				break;
		}
	}

	if ( ! $count ) {
		$count = $egDefaultCount;
	}

	if ( ! $service ) {
		$service = $egDefaultService;
	}	

	$output = getTweets( $user, $count, $service );

	return $output;
}

function getTweets( $user, $count, $service ) {
	global $egServices;	

	$serviceinfo = $egServices[$service];
	$twitter = new Service( $egServices[$service] );
	$response = $twitter->getPublicTimeline( $user, $count );
	
	if ( WikiError::isError( $response ) ) {
		$results = tweetError( $response->getMessage() );
		return $results;
	} else {
	        $results = '<div class="mw-twitterbox">
        	        <h4>' . ucwords( $serviceinfo['servicename'] ) . wfMsgHtml( 'twitter-feedheading' ) . $user . '</h4>';
	        $results .= '<ul class="mw-twitterlist">';

	        foreach( $response as $status ) {
	                $tweet = new Tweet( $status );
	                $results .= '<li class="mw-twitteritem">' . $tweet->output() . '</li>';
	        }
	        $results .= "</ul><div class='mw-twitterfollow'><a href='" . $serviceinfo['serviceurl'] . $user . "' class='twitter-follow'>" . wfMsgHtml( 'twitter-follow' ) . ucwords( $serviceinfo['servicename'] ) . "</a></div>
	        </div>";

		return $results;

	}	
}

function tweetError( $errormsg ) {
	wfDebug( $errormsg . '\n' );
        $error = new WikiError( $errormsg );
        $errorcode = Xml::element( 'span', array( 'class' => 'error' ), $error->getMessage() );
	return $errorcode;
}
